package top.caoayu.finance.tiancai;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.stereotype.Service;
import top.caoayu.finance.tiancai.VO.ResponseDataVO;
import javax.xml.namespace.QName;
import javax.xml.soap.*;
import java.io.IOException;
import java.util.Map;

/**
 * @author cxy
 */
@Service("tiancai/Client")
public class FinanceClient {

    private final String USERNAME = "admin";
    private final String PASSWD = "iOKBtg59e0NURwoJ2E20H+59ZlIxHschRyjLd4iTZCUPKh3ya8cm+A==";
    private final String URL = "http://202.117.218.241:9000/KBZWSCS/PZSJService.asmx";


    private SOAPMessage createSOAPRequest(String funName, Map<Object, Object> param) throws SOAPException, IOException {
        MessageFactory messageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
        SOAPMessage soapMessage = messageFactory.createMessage();
        // SOAP Part
        SOAPPart soapPart = soapMessage.getSOAPPart();
        // SOAP Envelope
        SOAPEnvelope envelope = soapPart.getEnvelope();

        this.setHeader(envelope,soapMessage,funName);
        this.setBody(envelope,funName,param);
        soapMessage.saveChanges();
        // Print the request message
        soapMessage.writeTo(System.out);
        return soapMessage;
    }

    /**
     * 设置 SOAP Header
     * @param envelope SOAP 消息
     * @param soapMessage SOAP 消息
     * @param funName 财务接口名称
     * @throws SOAPException SOAP 异常
     */
    private void setHeader(SOAPEnvelope envelope,SOAPMessage soapMessage, String funName) throws SOAPException {
        // SOAP Header
        SOAPHeader soapHeader = envelope.getHeader();
        Name headerElementName = envelope.createName("MySoapHeader", "", "http://tempuri.org/");
        SOAPHeaderElement soapHeaderElement = soapHeader.addHeaderElement(headerElementName);
        SOAPElement username = soapHeaderElement.addChildElement("UserName");
        username.addTextNode(USERNAME);
        SOAPElement password = soapHeaderElement.addChildElement("PassWord");
        password.addTextNode(PASSWD);
        // 设置请求属性
        MimeHeaders headers = soapMessage.getMimeHeaders();
        headers.addHeader("Content-Type", "application/soap+xml; charset=utf-8");
        headers.addHeader("SOAPAction", "http://tempuri.org/" + funName);
    }

    /**
     * 设置 SOAP Body
     * @param envelope SOAP 消息
     * @param funName 财务接口名称
     * @param param 请求参数
     * @throws SOAPException SOAP 异常
     */
    public void setBody(SOAPEnvelope envelope, String funName, Map<Object, Object> param) throws SOAPException {
        // SOAP Body
        SOAPBody soapBody = envelope.getBody();
        Name bodyElementName = envelope.createName(funName, "", "http://tempuri.org/");
        SOAPBodyElement soapBodyElement = soapBody.addBodyElement(bodyElementName);
        for (Map.Entry<Object, Object> objectObjectEntry : param.entrySet()) {
            SOAPElement soapElement = soapBodyElement.addChildElement(objectObjectEntry.getKey().toString());
            soapElement.addTextNode(objectObjectEntry.getValue().toString());
        }
    }
    /**
     * 获取 SOAP 响应
     * @param soapMessage SOAP 消息
     * @param funName    财务接口名称
     * @return String 财务接口返回数据
     * @throws SOAPException SOAP 异常
     * @throws IOException  IO 异常
     */
    public static String getSoapResponse(SOAPMessage soapMessage, String funName) throws SOAPException, IOException {
        // 获取 SOAP 消息的主体
        SOAPBody soapBody = soapMessage.getSOAPBody();

        // 获取 response 元素
        SOAPElement responseElement = (SOAPElement) soapBody.getChildElements().next();

        // 获取 result 元素
        SOAPElement resultElement = (SOAPElement) responseElement.getChildElements(new QName("http://tempuri.org/", funName + "Result")).next();

        // 获取 result 元素的文本内容
        String resultValue = resultElement.getTextContent();
//        ByteArrayOutputStream responseStream = new ByteArrayOutputStream();
//        soapMessage.writeTo(responseStream);

        soapMessage.writeTo(System.out);

//        String rawResponse = new String(responseStream.toByteArray(), "utf-8");
        return resultValue;

    }

    /**
     * 调用财务接口
     *
     * @param funName 财务接口名称
     * @param param   请求参数
     * @return List<FinanceVo> 财务接口数据
     */
    public <T> ResponseDataVO<T> getFinanceData(String funName, Map<Object, Object> param,
                                                TypeReference<T> responseType){
        try {
            SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
            SOAPConnection soapConnection = soapConnectionFactory.createConnection();
            SOAPMessage soapResponse = soapConnection.call(createSOAPRequest(funName, param), URL);
            String response = getSoapResponse(soapResponse, funName);
            soapConnection.close();
            return responseToJson(response,responseType);
        } catch (SOAPException | IOException e) {
            throw new RuntimeException("财务请求处理失败：" + e.getMessage());
        }
    }

    public static <T> ResponseDataVO<T> responseToJson(String response, TypeReference<T> dataType) {
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            JsonNode dataNode = objectMapper.readTree(response).get("DATA");
            T data = objectMapper.readValue(dataNode.traverse(), dataType);

            // 创建一个新的 ResponseDataVO，保留原始的 flag，并设置解析后的 data
            ResponseDataVO<T> responseDataVO = new ResponseDataVO<>();
            responseDataVO.setFlag(objectMapper.readTree(response).get("FLAG").asText());
            responseDataVO.setData(data);

            return responseDataVO;
        } catch (IOException e) {
            throw new RuntimeException("财务接口返回数据解析失败：" + e.getMessage());
        }
    }
}
